package visiopuce.service;

import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import visiopuce.ApplicationContexte;
import visiopuce.HibernateUtil;
import visiopuce.DAO.AlterationDAOImpl;
import visiopuce.DAO.ChampDAOImpl;
import visiopuce.DAO.ControleQualiteDAO;
import visiopuce.DAO.ControleQualiteDAOImpl;
import visiopuce.DAO.HistoriqueDAO;
import visiopuce.DAO.HistoriqueDAOImpl;
import visiopuce.DAO.PuceDAO;
import visiopuce.DAO.PuceDAOImpl;
import visiopuce.DAO.ResultatDAOImpl;
import visiopuce.objets.Alteration;
import visiopuce.objets.Bande;
import visiopuce.objets.Biomedecine;
import visiopuce.objets.ControleQualite;
import visiopuce.objets.Historique;
import visiopuce.objets.Puce;
import visiopuce.objets.Resultat;
import visiopuce.objets.TypePuce;

public class PuceServiceImpl implements PuceService {

	private static final Log log = LogFactory.getLog(PrelevementService.class);

	private PuceDAO puceDAO = PuceDAOImpl.getInstance();
	private ControleQualiteDAO controleQualiteDAO = ControleQualiteDAOImpl.getInstance();
	private HistoriqueDAO historiqueDAO = HistoriqueDAOImpl.getInstance();

	/** Constructeur priv� */
	private PuceServiceImpl() {
	}

	/** Instance unique non pr�initialis�e */
	private static PuceServiceImpl INSTANCE = null;

	/** Point d'acc�s pour l'instance unique du singleton */
	public static PuceService getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new PuceServiceImpl();
		}
		return INSTANCE;
	}

	public List<Puce> findAllByidAnalyse(Integer idAnalyse) {
		List<Puce> puces = null;

		HibernateUtil.beginTransaction();
		puces = puceDAO.findAllByidAnalyse(idAnalyse);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();

		return puces;
	}

	public Puce refresh(Puce puce) {
		if (puce.getIdPuce() != 0) {
			HibernateUtil.beginTransaction();
			HibernateUtil.getSession().refresh(puce);
			HibernateUtil.closeSession();
		}
		return puce;
	}

	@Override
	public Puce getPuceByid(int idPuce) {
		Puce puce = null;
		HibernateUtil.beginTransaction();
		puce = puceDAO.findByID(Puce.class, idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return puce;
	}

	@Override
	public ControleQualite getQCByPuceTypeQc(Puce puce, String libelleTypeQc) {
		ControleQualite qcs = null;
		HibernateUtil.beginTransaction();
		qcs = controleQualiteDAO.getQCByPuceTypeQc(puce, libelleTypeQc);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return qcs;
	}

	@Override
	public boolean isPucePrincipale(int idPuce) {
		boolean res = false;
		HibernateUtil.beginTransaction();
		res = puceDAO.isPucePrincipale(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return res;
	}

	@Override
	public void save(Puce puce) {
		HibernateUtil.beginTransaction();
		try {

			puceDAO.save(puce);

			Historique h = new Historique();
			h.setDate(new Date());
			h.setRequete("Enregistrement " + puce.toString());
			h.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
			historiqueDAO.save(h);

			List<ControleQualite> qcs = puce.getQcs();
			if (qcs != null) {
				for (ControleQualite controleQualite : qcs) {
					controleQualiteDAO.save(controleQualite);
					Historique h2 = new Historique();
					h2.setDate(new Date());
					h2.setRequete("Enregistrement " + controleQualite.toString());
					h2.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
					historiqueDAO.save(h2);
				}
			}
			HibernateUtil.commitTransaction();
		} catch (Exception ex) {
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
		} finally {
			HibernateUtil.closeSession();
		}
	}

	@Override
	public Biomedecine getIndicationByIdPuce(Integer idPuce) {
		Biomedecine bm = null;
		HibernateUtil.beginTransaction();
		bm = puceDAO.getIndicationByIdPuce(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return bm;
	}

	@Override
	public String getSexePersonneByIdPuce(Integer idPuce) {
		String sexe = null;
		HibernateUtil.beginTransaction();
		sexe = puceDAO.getSexePersonneByIdPuce(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return sexe;
	}

	@Override
	public boolean getIsPatientByIdPuce(Integer idPuce) {
		boolean isPatient = false;
		HibernateUtil.beginTransaction();
		isPatient = puceDAO.getIsPatientByIdPuce(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return isPatient;
	}

	@Override
	public int getIdPersonneByIdPuce(Integer idPuce) {
		int idPersonne = 0;
		HibernateUtil.beginTransaction();
		idPersonne = puceDAO.getIdPersonneByIdPuce(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return idPersonne;
	}

	@Override
	public TypePuce getTypePuceByIdPuce(Integer idPuce) {
		TypePuce typePuce = null;
		HibernateUtil.beginTransaction();
		typePuce = puceDAO.getTypePuceByIdPuce(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return typePuce;
	}

	@Override
	public String[] genereFormuleConclusionPuce(Puce p) {
		String formule = "";
		String conclusion = "";
		String chromosomes = "";
		HibernateUtil.beginTransaction();
		List<Alteration> alterations = AlterationDAOImpl.getInstance().getCNVFormule(p.getIdPuce());
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		String sexe = PuceServiceImpl.getInstance().getSexePersonneByIdPuce(p.getIdPuce());
		if (sexe.isEmpty()) {
			HibernateUtil.beginTransaction();
			sexe = ChampDAOImpl.getInstance().getSexeFoetusByIdPuce(p.getIdPuce());
			HibernateUtil.commitTransaction();
			HibernateUtil.closeSession();
		}
		if (alterations.size() == 0) {
			if (sexe != null) {
				if (sexe.equals("M")) {
					formule = "arr(1-22)x2,(XY)x1";
				} else if (sexe.equals("F")) {
					formule = "arr(1-22,X)x2";
				} else {
					formule = "IL MANQUE LE SEXE DE LA PERSONNE OU DU FOETUS";
				}
			} else {
				formule = "IL MANQUE LE SEXE DE LA PERSONNE OU DU FOETUS";
			}
			conclusion = "Pas de microréarrangement chromosomique retenu selon les conditions expérimentales et les paramètres d'analyse utilisés.";
		} else {
			conclusion = "Mise en évidence sur puce à ADN de :\r\n";
			for (Alteration alteration : alterations) {
				String suite = "";
				String bandesChr = "";
				chromosomes += alteration.getChromosome() + ";";
				List<Bande> bandes = ReferentielServiceImpl.getInstance().getBandesByCNV(alteration);
				for (Bande bande : bandes) {
					bandesChr += bande.getLibelle();
				}
				// resultat: 56 789,12 Euro
				formule += "arr " + alteration.getChromosome() + bandesChr + "(" + NumberFormat.getNumberInstance(Locale.US).format(alteration.getDebutHg19()) + "-" + NumberFormat.getNumberInstance(Locale.US).format(alteration.getFinHg19()) + ")x" + new Double(alteration.getNbCopie()).intValue()
						+ "\r\n";
				double taille = Math.round((alteration.getFinHg19() - alteration.getDebutHg19()) / 1000);
				if (alteration.getNbCopie() >= 2) {
					conclusion += "\t- une duplication (gain)";
					suite = " Cette duplication [contient/coupe]";
				}
				if (alteration.getNbCopie() < 2) {
					conclusion += "\t- une délétion (perte)";
					suite = " Cette délétion [emporte/coupe]";
				}
				if (alteration.getSondeDebut() == null || alteration.getSondeDebut().equals("")) {
					alteration.setSondeDebut(ReferentielServiceImpl.getInstance().getProbeByAlteration(alteration.getChromosome(), alteration.getDebutHg19(), p.getTypePuce().getIdTypePuce()));
				}
				if (alteration.getSondeFin() == null || alteration.getSondeFin().equals("")) {
					alteration.setSondeFin(ReferentielServiceImpl.getInstance().getProbeByAlteration(alteration.getChromosome(), alteration.getFinHg19(), p.getTypePuce().getIdTypePuce()));
				}
				String sDeb = "NOM DE SONDE MANQUANTE";
				if (alteration.getSondeDebut() != null){
					sDeb = alteration.getSondeDebut().trim();
				}
				String sFin = "NOM DE SONDE MANQUANTE";
				if (alteration.getSondeDebut() != null){
					sFin = alteration.getSondeFin().trim();
				}
				conclusion += "[interstitielle] d'environ " + taille + " kb de la région chromosomique " + alteration.getChromosome() + bandesChr + " entre les marqueurs " + sDeb + " (" + NumberFormat.getInstance().format(alteration.getDebutHg19()) + " pb) et "
						+ sFin + " (" + NumberFormat.getInstance().format(alteration.getFinHg19()) + " pb).";
				conclusion += suite + " notamment [le(s) gène(s)/une partie du gène ...rapport géne/phénotype?].\r\n";

			}
			conclusion += "Cependant, il est nécessaire de vérifier, par une autre technique, ";
			if (alterations.size() > 1) {
				conclusion += "ces remaniements et de les ";
			} else {
				conclusion += "ce remaniement et de le ";
			}
			conclusion += "rechercher chez les parents pour en déterminer le caractère de novo ou transmis. Un conseil génétique est souhaitable.\r\n";
			conclusion += "Nous tenons à votre disposition la liste du/des gène(s) et/ou pseudogène(s) présent(s) dans";
			if (alterations.size() > 1) {
				conclusion += " ces remaniements.";
			} else {
				conclusion += " ce remaniement.";
			}
		}

		HibernateUtil.beginTransaction();
		List<Resultat> resultats = ResultatDAOImpl.getInstance().getResulatMicrosatByIdAnalysePuce(p.getAnalyse().getIdAnalyse());
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		if (resultats != null && resultats.size() > 0) {
			for (Resultat resultat : resultats) {
				if (resultat.getResultat().equals("Normal")) {
					conclusion += "\r\nContrôle de l'absence de contamination maternelle du prélèvement foetal par l'analyse de ségrégation de marqueurs microsatlellites à l'aide du kit STR Promega Powerplex® 16 HS (15 marqueurs microsatellites autosomiques, séquenceur ABI).\r\n";
				}
			}
		}

		String[] result = new String[3];
		result[0] = formule;
		result[1] = conclusion;
		result[2] = chromosomes;
		return result;
	}

	@Override
	public HashMap<String, Puce> getPuceFromFeuillePuce(int idFeuillePuce) {
		HashMap<String, Puce> puces = null;

		HibernateUtil.beginTransaction();
		puces = puceDAO.getPuceFromFeuillePuce(idFeuillePuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();

		return puces;
	}

	@Override
	public void delete(Puce puce) {
		HibernateUtil.beginTransaction();
		try {
			Historique h3 = new Historique();
			h3.setDate(new Date());
			h3.setRequete("Suppression " + puce.toString());
			h3.setUtilisateur(ApplicationContexte.getInstance().getUtilisateur());
			historiqueDAO.save(h3);

			puceDAO.delete(puce);

			HibernateUtil.commitTransaction();
		} catch (Exception ex) {
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
		} finally {
			HibernateUtil.closeSession();
		}
	}

	@Override
	public String getNumeroPrelevementByidPuce(Integer idPuce) {
		String num = null;
		HibernateUtil.beginTransaction();
		num = puceDAO.getNumeroPrelevementByidPuce(idPuce);
		HibernateUtil.commitTransaction();
		HibernateUtil.closeSession();
		return num;
	}
}